# -*- coding: utf - 8 -*-
"""
标准化API接口模块
提供RESTful API和插件扩展机制
"""

from flask import Flask, request, jsonify, send_file
from flask_cors import CORS
import os
# import json  # noqa: F401
import logging
from typing import Dict, Any, List, Optional
from dataclasses import dataclass, asdict
import threading
import time
from werkzeug.utils import secure_filename
import tempfile
import uuid

from .main import MigrationTool
from .performance import performance_profiler
# from .stability import stability_manager  # noqa: F401

logger = logging.getLogger(__name__)


@dataclass
class APIResponse:
    """标准API响应格式"""
    success: bool
    message: str
    data: Optional[Any] = None
    error_code: Optional[str] = None
    timestamp: float = None

    def __post_init__(self):
        if self.timestamp is None:
            self.timestamp = time.time()

    def to_dict(self) -> Dict[str, Any]:
        return asdict(self)


class MigrationAPI:
    """迁移工具API类"""

    def __init__(self):
        self.app = Flask(__name__)
        CORS(self.app)
        self.migration_tool = MigrationTool()
        self.active_jobs = {}
        self.job_results = {}
        self._setup_routes()

    def _setup_routes(self):
        """设置API路由"""

        @self.app.route('/api/v1/ health', methods=['GET'])
        def health_check():
            """健康检查"""
            return jsonify(APIResponse(
                success=True,
                message="服务正常运行",
                data={
                    "version": "1.0.0",
                    "status": "healthy",
                    "uptime": time.time()
                }
            ).to_dict())

        @self.app.route('/api/v1/ migrate', methods=['POST'])
        def migrate():
            """执行迁移任务"""
            try:
                # 解析请求参数
                data = request.get_json()
                if not data:
                    return jsonify(APIResponse(
                        success=False,
                        message="请求体不能为空",
                        error_code="INVALID_REQUEST"
                    ).to_dict()), 400

                input_file = data.get('input_file')
                output_file = data.get('output_file')
                options = data.get('options', {})

                if not input_file:
                    return jsonify(APIResponse(
                        success=False,
                        message="缺少输入文件参数",
                        error_code="MISSING_INPUT_FILE"
                    ).to_dict()), 400

                # 创建异步任务
                job_id = str(uuid.uuid4())
                thread = threading.Thread(
                    target=self._execute_migration,
                    args=(job_id, input_file, output_file, options)
                )
                thread.daemon = True
                thread.start()

                self.active_jobs[job_id] = {
                    'status': 'running',
                    'start_time': time.time(),
                    'input_file': input_file,
                    'output_file': output_file
                }

                return jsonify(APIResponse(
                    success=True,
                    message="迁移任务已启动",
                    data={'job_id': job_id}
                ).to_dict())

            except Exception as e:
                logger.error(f"迁移API错误: {e}")
                return jsonify(APIResponse(
                    success=False,
                    message=f"服务器内部错误: {str(e)}",
                    error_code="INTERNAL_ERROR"
                ).to_dict()), 500

        @self.app.route('/api/v1/ jobs/<job_id>', methods=['GET'])
        def get_job_status(job_id):
            """获取任务状态"""
            if job_id in self.active_jobs:
                job_info = self.active_jobs[job_id].copy()
                job_info['duration'] = time.time() - job_info['start_time']
                return jsonify(APIResponse(
                    success=True,
                    message="任务状态获取成功",
                    data=job_info
                ).to_dict())

            elif job_id in self.job_results:
                return jsonify(APIResponse(
                    success=True,
                    message="任务结果获取成功",
                    data=self.job_results[job_id]
                ).to_dict())

            else:
                return jsonify(APIResponse(
                    success=False,
                    message="任务不存在",
                    error_code="JOB_NOT_FOUND"
                ).to_dict()), 404

        @self.app.route('/api/v1/ jobs', methods=['GET'])
        def list_jobs():
            """列出所有任务"""
            all_jobs = {}
            all_jobs.update(self.active_jobs)
            all_jobs.update(self.job_results)

            return jsonify(APIResponse(
                success=True,
                message="任务列表获取成功",
                data=all_jobs
            ).to_dict())

        @self.app.route('/api/v1/ upload', methods=['POST'])
        def upload_file():
            """上传SQL文件"""
            try:
                if 'file' not in request.files:
                    return jsonify(APIResponse(
                        success=False,
                        message="没有文件上传",
                        error_code="NO_FILE"
                    ).to_dict()), 400

                file = request.files['file']
                if file.filename == '':
                    return jsonify(APIResponse(
                        success=False,
                        message="文件名不能为空",
                        error_code="EMPTY_FILENAME"
                    ).to_dict()), 400

                # 保存文件
                filename = secure_filename(file.filename)
                upload_dir = os.path.join(tempfile.gettempdir(), 'migration_uploads')
                os.makedirs(upload_dir, exist_ok=True)

                file_path = os.path.join(upload_dir, f"{uuid.uuid4()}_{filename}")
                file.save(file_path)

                return jsonify(APIResponse(
                    success=True,
                    message="文件上传成功",
                    data={
                        'file_path': file_path,
                        'filename': filename,
                        'size': os.path.getsize(file_path)
                    }
                ).to_dict())

            except Exception as e:
                logger.error(f"文件上传错误: {e}")
                return jsonify(APIResponse(
                    success=False,
                    message=f"文件上传失败: {str(e)}",
                    error_code="UPLOAD_ERROR"
                ).to_dict()), 500

        @self.app.route('/api/v1/ download/<job_id>', methods=['GET'])
        def download_result(job_id):
            """下载迁移结果"""
            if job_id not in self.job_results:
                return jsonify(APIResponse(
                    success=False,
                    message="任务结果不存在",
                    error_code="RESULT_NOT_FOUND"
                ).to_dict()), 404

            result = self.job_results[job_id]
            if not result.get('success') or not result.get('output_file'):
                return jsonify(APIResponse(
                    success=False,
                    message="任务未成功完成或输出文件不存在",
                    error_code="NO_OUTPUT_FILE"
                ).to_dict()), 400

            output_file = result['output_file']
            if not os.path.exists(output_file):
                return jsonify(APIResponse(
                    success=False,
                    message="输出文件不存在",
                    error_code="FILE_NOT_FOUND"
                ).to_dict()), 404

            return send_file(output_file, as_attachment=True)

        @self.app.route('/api/v1/ validate', methods=['POST'])
        def validate_sql():
            """验证SQL文件"""
            try:
                data = request.get_json()
                sql_content = data.get('sql_content')
                file_path = data.get('file_path')

                if not sql_content and not file_path:
                    return jsonify(APIResponse(
                        success=False,
                        message="需要提供SQL内容或文件路径",
                        error_code="MISSING_SQL"
                    ).to_dict()), 400

                # 执行验证
                validation_result = self.migration_tool.validate_sql(
                    sql_content=sql_content,
                    file_path=file_path
                )

                return jsonify(APIResponse(
                    success=True,
                    message="SQL验证完成",
                    data=validation_result
                ).to_dict())

            except Exception as e:
                logger.error(f"SQL验证错误: {e}")
                return jsonify(APIResponse(
                    success=False,
                    message=f"验证失败: {str(e)}",
                    error_code="VALIDATION_ERROR"
                ).to_dict()), 500

        @self.app.route('/api/v1/ stats', methods=['GET'])
        def get_statistics():
            """获取系统统计信息"""
            try:
                stats = {
                    'active_jobs': len(self.active_jobs),
                    'completed_jobs': len(self.job_results),
                    'system_info': {
                        'cpu_count': os.cpu_count(),
                        'memory_usage': self._get_memory_usage(),
                    },
                    'performance_metrics': performance_profiler.metrics
                }

                return jsonify(APIResponse(
                    success=True,
                    message="统计信息获取成功",
                    data=stats
                ).to_dict())

            except Exception as e:
                logger.error(f"统计信息获取错误: {e}")
                return jsonify(APIResponse(
                    success=False,
                    message=f"获取统计信息失败: {str(e)}",
                    error_code="STATS_ERROR"
                ).to_dict()), 500

    def _execute_migration(self, job_id: str, input_file: str,
                           output_file: str, options: Dict[str, Any]):
        """执行迁移任务"""
        try:
            # 开始性能监控
            _metrics = performance_profiler.start_session(job_id)  # noqa: F841

            # 执行迁移
            result = self.migration_tool.migrate(
                input_file=input_file,
                output_file=output_file,
                **options
            )

            # 结束性能监控
            performance_profiler.end_session(job_id)

            # 保存结果
            self.job_results[job_id] = {
                'status': 'completed',
                'success': result.get('success', False),
                'message': result.get('message', ''),
                'output_file': output_file,
                'start_time': self.active_jobs[job_id]['start_time'],
                'end_time': time.time(),
                'performance_metrics': performance_profiler.get_report(job_id),
                'details': result
            }

        except Exception as e:
            logger.error(f"迁移任务执行失败 {job_id}: {e}")
            self.job_results[job_id] = {
                'status': 'failed',
                'success': False,
                'message': f"迁移失败: {str(e)}",
                'start_time': self.active_jobs[job_id]['start_time'],
                'end_time': time.time(),
                'error': str(e)
            }

        finally:
            # 清理活动任务
            self.active_jobs.pop(job_id, None)

    def _get_memory_usage(self) -> Dict[str, Any]:
        """获取内存使用情况"""
        try:
            import psutil
            memory = psutil.virtual_memory()
            return {
                'total_mb': memory.total / 1024 / 1024,
                'used_mb': memory.used / 1024 / 1024,
                'available_mb': memory.available / 1024 / 1024,
                'percent': memory.percent
            }
        except ImportError:
            return {'error': 'psutil not available'}

    def run(self, host: str = '0.0.0.0', port: int = 8080, debug: bool = False):
        """启动API服务"""
        logger.info(f"启动API服务: http://{host}:{port}")
        self.app.run(host=host, port=port, debug=debug, threaded=True)


class PluginManager:
    """插件管理器"""

    def __init__(self):
        self.plugins = {}
        self.hooks = {
            'before_parse': [],
            'after_parse': [],
            'before_convert': [],
            'after_convert': [],
            'before_generate': [],
            'after_generate': []
        }

    def register_plugin(self, name: str, plugin_class):
        """注册插件"""
        try:
            plugin_instance = plugin_class()
            self.plugins[name] = plugin_instance

            # 注册钩子
            for hook_name in self.hooks.keys():
                if hasattr(plugin_instance, hook_name):
                    self.hooks[hook_name].append(getattr(plugin_instance, hook_name))

            logger.info(f"插件注册成功: {name}")
            return True

        except Exception as e:
            logger.error(f"插件注册失败 {name}: {e}")
            return False

    def execute_hook(self, hook_name: str, *args, **kwargs):
        """执行钩子"""
        if hook_name not in self.hooks:
            return

        for hook_func in self.hooks[hook_name]:
            try:
                hook_func(*args, **kwargs)
            except Exception as e:
                logger.error(f"钩子执行失败 {hook_name}: {e}")

    def get_plugin(self, name: str):
        """获取插件实例"""
        return self.plugins.get(name)

    def list_plugins(self) -> List[str]:
        """列出所有插件"""
        return list(self.plugins.keys())


# 全局实例
migration_api = MigrationAPI()
plugin_manager = PluginManager()


def create_app():
    """创建Flask应用的工厂函数"""
    api = MigrationAPI()
    return api.app


# CLI入口点
def main():
    """CLI入口点"""
    import argparse
    
    parser = argparse.ArgumentParser(description='MySQL到KWDB迁移工具API服务')
    parser.add_argument('--host', default='0.0.0.0', help='服务器地址')
    parser.add_argument('--port', type=int, default=8080, help='服务器端口')
    parser.add_argument('--debug', action='store_true', help='调试模式')
    
    args = parser.parse_args()
    
    # 启动API服务
    migration_api.run(host=args.host, port=args.port, debug=args.debug)


if __name__ == '__main__':
    main()
